import 'package:dio/dio.dart';
import 'package:flutter_easylogger/flutter_logger.dart';

/// 自定义Dio日志拦截器
class CustomLogInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    String requestStr = "\n==================== 请求信息 ====================\n"
        "- URL:\n${options.baseUrl + options.path}\n"
        "- 请求方法: ${options.method}\n";

    requestStr += "- 请求头:\n${options.headers.mapToStructureString()}\n";

    final data = options.data;
    if (data != null) {
      if (data is Map) {
        requestStr += "- 请求体:\n${data.mapToStructureString()}\n";
      } else if (data is FormData) {
        final formDataMap = {}
          ..addEntries(data.fields)
          ..addEntries(data.files);
        requestStr += "- 请求体:\n${formDataMap.mapToStructureString()}\n";
      } else if (data is List) {
        requestStr += "- 请求体:\n${data.listToStructureString()}\n";
      } else {
        requestStr += "- 请求体:\n${data.toString()}\n";
      }
    }

    final queryParameters = options.queryParameters;
    if (queryParameters.isNotEmpty) {
      requestStr += "- 查询参数:\n${queryParameters.mapToStructureString()}\n";
    }

    printWrapped(requestStr);
    super.onRequest(options, handler);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    String errorStr = "\n==================== 错误信息 ====================\n"
        "- URL:\n${err.requestOptions.baseUrl + err.requestOptions.path}\n"
        "- 请求方法: ${err.requestOptions.method}\n"
        "- 错误类型: ${err.type.toString()}\n";

    if (err.response != null) {
      errorStr += "- 状态码: ${err.response!.statusCode ?? "未知"}\n";

      if (err.response!.headers.map.isNotEmpty) {
        errorStr += "- 响应头:\n${err.response!.headers.map.mapToStructureString()}\n";
      }

      if (err.response!.data != null) {
        errorStr += "- 错误响应:\n${_parseResponse(err.response!)}\n";
      }
    } else {
      errorStr += "- 错误信息: ${err.message}\n";
    }

    printWrapped(errorStr);
    super.onError(err, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    String responseStr = "\n==================== 响应信息 ====================\n"
        "- URL:\n${response.requestOptions.uri}\n"
        "- 请求方法: ${response.requestOptions.method}\n"
        "- 状态码: ${response.statusCode}\n";

    if (response.headers.map.isNotEmpty) {
      responseStr += "- 响应头:\n${response.headers.map.mapToStructureString()}\n";
    }

    if (response.data != null) {
      responseStr += "- 响应体:\n${_parseResponse(response)}\n";
    }

    printWrapped(responseStr);
    super.onResponse(response, handler);
  }

  void printWrapped(String text) {
    Logger.v(text);
  }

  String _parseResponse(Response response) {
    String responseStr = "";
    var data = response.data;
    if (data is Map) {
      responseStr += data.mapToStructureString();
    } else if (data is List) {
      responseStr += data.listToStructureString();
    } else {
      responseStr += response.data.toString();
    }

    return responseStr;
  }
}

extension Map2StringEx on Map {
  String mapToStructureString({int indentation = 2}) {
    String result = "";
    String indentationStr = " " * indentation;
    if (isEmpty) {
      return "{}";
    }

    result += "{";
    forEach((key, value) {
      if (value is Map) {
        var temp = value.mapToStructureString(indentation: indentation + 2);
        result += "\n$indentationStr" "\"$key\": $temp,";
      } else if (value is List) {
        result += "\n$indentationStr" "\"$key\": ${value.listToStructureString(indentation: indentation + 2)},";
      } else {
        result += "\n$indentationStr" "\"$key\": \"$value\",";
      }
    });

    if (isNotEmpty) {
      result = result.substring(0, result.length - 1);
    }

    result += indentation == 2 ? "\n}" : "\n${" " * (indentation - 1)}}";

    return result;
  }
}

extension List2StringEx on List {
  String listToStructureString({int indentation = 2}) {
    String result = "";
    String indentationStr = " " * indentation;

    if (isEmpty) {
      return "[]";
    }

    result += "[";
    for (var value in this) {
      if (value is Map) {
        var temp = value.mapToStructureString(indentation: indentation + 2);
        result += "\n$indentationStr$temp,";
      } else if (value is List) {
        result += "\n$indentationStr${value.listToStructureString(indentation: indentation + 2)},";
      } else {
        result += "\n$indentationStr\"$value\",";
      }
    }

    if (isNotEmpty) {
      result = result.substring(0, result.length - 1);
    }

    result += "\n${" " * (indentation - 2)}]";

    return result;
  }
}